package us.versus.them.b3ge.phyxside;

import us.versus.them.b3ge.events.Key;

import flash.net.URLRequest;
import flash.display.Sprite;
import flash.events.KeyboardEvent;
import flash.events.Event;

import phx.Vector;

/**
 *
 * The app is primarly concerned with:
 * <ul>
 *    <li>handling key events</li>
 *    <li>keeping the actor on the screen</li>
 *    <li>loading boards</li>
 *    <li>handling the goal</li>
 *    <li>x</li>
 * </ul>
 *
 *
 *
 *
 */
class App extends Worldly {

	public static var LEVEL_PATH = "./data/svg/level.XXX.svg";
	public static var FLIP = 'app';

	var goal : phx.Vector;
	var currentLevel : Int;
	var key : Key;

	////

	static var run       =  5.0;
	static var airMod    =  0.5;//1.05;
	static var wakeUpHop =  5.0;
	static var brakes    =  0.5;
	static var jump      = 15.0;
	static var max       = 15.0;

	////

	public function new( flipper:Flipper ) {
		super( flipper );
	}

	public override function starterWorld() {
		currentLevel = 0;
		this.loadLevel();
	}

	public function prevLevel() {
		currentLevel--;
		loadLevel();
	}

	public function nextLevel() {
		currentLevel++;
		loadLevel();
	}

	public function loadLevel() {
		this.useLoadingLoop();
		createWorld();
		//trace( 'load ' + svg() );
		new Board( this, svg() );
	}

	public function svg() {
		return ~/XXX/.replace( 
			LEVEL_PATH
			, StringTools.lpad( "" + currentLevel, "0", 4 ) 
		);
	}

	public override function goalTo( x : Float, y : Float ) {
		goal = new Vector( x, y );
	}

	public override function preWorldLoop( event:Event ) {
		moveLeftRight( 
			key.isDown( Key.K_ARROW_LEFT )
			, key.isDown( Key.K_ARROW_RIGHT )
			, key.isDown( Key.K_SHIFT )
		);
		keepActorOnScreen( bob, 400, 300, Worldly.bobSize * 2, Worldly.bobSize * 3 );
	}

	public override function postWorldLoop( event:Event ) {
		var g = graphics;

		// goal!
		g.beginFill( Math.floor( 0xFFFFFF * Math.random() ) );
		g.lineStyle( 4, 0x000020 );
		g.drawRect( goal.x, goal.y, Worldly.bobSize * 2, Worldly.bobSize * 2 );
		if (
			   bob.x >= goal.x && bob.x <= goal.x + Worldly.bobSize * 2 
			&& bob.y >= goal.y && bob.y <= goal.y + Worldly.bobSize * 2 
		) { 
			nextLevel();
			return;
		}

		if ( bob.v.y > 40 ) {
			this.loadLevel();
		}
	}

	public function keepActorOnScreen( 
		actor : phx.Body
		, screenWidth : Float
		, screenHeight : Float
		, xPadding : Float 
		, yPadding : Float 
	) {

		// too left
		if ( actor.x < this.x + xPadding ) {
			this.x = -actor.x + xPadding; 
		} else 
		// too right
		if ( actor.x > this.x + screenWidth - xPadding ) {
			this.x = -actor.x + screenWidth - xPadding;
		}

		// too down
		if ( screenHeight - actor.y - yPadding < this.y ) {
			this.y = screenHeight - actor.y - yPadding;
		} else
		// too up
		if ( actor.y < - this.y + yPadding ) {
			this.y = - actor.y + yPadding;
		}
	}

	public override function listenMore() {
		key = new Key( flash.Lib.current.stage );
		key.setCallBack( Key.K_ARROW_UP, jumpUp );
		key.setCallBack( Key.K_SPACE, brake );
		key.setCallBack( Key.K_ARROW_DOWN, brake );
		key.setCallBack( Key.K_R, loadLevel );
		key.setCallBack( Key.K_N, nextLevel );
		key.setCallBack( Key.K_ADD, nextLevel );
		key.setCallBack( Key.K_SUBTRACT, prevLevel );
		key.setCallBack( Key.K_P, prevLevel );
		key.setCallBack( Key.K_ESCAPE, starterWorld );
	}

	////

	public function jumpUp() {
		if ( !isFalling( bob ) ) {
			bob.v.y -= jump;  
			if ( null != bob.island ) {
				world.activate( bob );
			}
		}
	}

	public function moveLeftRight( left:Bool, right:Bool, shift:Bool ) {
		if ( left || right ) {
			var add = if ( left ) -run; else run;
			if ( shift ) {
				this.x -= add;
			} else {
				if ( isFalling( bob ) ) {
					add *= airMod;
				}
				var nu_x = bob.v.x + add;
				if ( nu_x < -max ) nu_x = -max;
				if ( nu_x > max ) nu_x = max;
				bob.setSpeed( nu_x, bob.v.y );
				if ( null != bob.island && bob.island.sleeping ) {
					world.activate( bob );
					bob.v.y -= wakeUpHop;
				}
			}
		}
	}

	public function brake() {
		bob.v.x *= brakes;
	}

}
